export class Point {
    constructor(public x: number, public y: number) {
        this.x = x
        this.y = y
    }
}

class Graphic {
    constructor(private name: string, private point: Point = new Point(0, 0)) {
        this.name = name
        this.point = point
    }
    move(delta: Point, direction: number) {
        switch (direction) {
            case 0:
                console.log(`${this.name},向(${delta.x}, ${delta.y})方向移动`);
                break
            case 1:
                console.log(`${this.name},向(${-delta.x}, ${-delta.y})方向移动`);
                break
        }
    }
}

class MoveCommand {
    declare private _delta: Point
    declare private _target: Graphic
    declare private _state: ConstraintSolverMemento
    constructor(target: Graphic, delta: Point) {
        this._target = target
        this._delta = delta
    }

    execute() {
        const solver = ConstraintSolver.instance()
        this._state = solver.createMemento(this)//创建一个备忘录
        solver.setMemento(this._state)
        this._target.move(this._delta, 0)
        solver.solve()
    }
    unExecute() {
        const solver = ConstraintSolver.instance()
        this._target.move(this._delta, 1)
        solver.solve()
    }
}

//Originator
class ConstraintSolver {

    private static declare _instance: ConstraintSolver
    private declare _memento: ConstraintSolverMemento[]
    static instance(): ConstraintSolver {

        if (!this._instance) {
            this._instance = new ConstraintSolver()
        }
        return this._instance

    }
    private constructor() {
        this._memento = []
    }
    solve(): void {

    }
    addConstraint(startConnection: Graphic, endConnection: Graphic): void {

    }
    removeConstraint(startConnection: Graphic, endConnection: Graphic): void {

    }
    createMemento(command: MoveCommand): ConstraintSolverMemento {
        return new ConstraintSolverMemento(command)
    }
    setMemento(memento: ConstraintSolverMemento): void {
        this._memento.push(memento)
    }
    getMemento() {
        return this._memento.pop()

    }
}


class ConstraintSolverMemento {
    declare private _command: MoveCommand

    constructor(command: MoveCommand) {
        this._command = command
    }
    get() {
        return this._command
    }
}


const g1 = new Graphic('正方形1')
const g2 = new Graphic('正方形2')

//模拟鼠标拖动
const moveCommand = new MoveCommand(g1, new Point(3, 6))
moveCommand.execute()
const moveCommand2 = new MoveCommand(g1, new Point(6, 6))
moveCommand2.execute()
ctrl_z()
const moveCommand3 = new MoveCommand(g1, new Point(76, 26))
moveCommand3.execute()

//模拟ctrl+z


ctrl_z()
ctrl_z()
ctrl_z()
function ctrl_z() {
    const solver = ConstraintSolver.instance()
    const momento = solver.getMemento()
    if (momento) {
        momento.get().unExecute()
    } else {
        console.log('无可撤销操作');
    }
}